package pl.edu.pb.wi.cookbook.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

import javax.validation.Valid;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import pl.edu.pb.wi.cookbook.form.ShortenUrlForm;

import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;

@Controller
public class ShortenUrlController {
    private static final Logger log = Logger
            .getLogger(ShortenUrlController.class.getName());
    private static final String SHORTENER_URL = "https://www.googleapis.com/auth/urlshortener";
    private static final String SHORTENER_REQUEST_URL = "https://www.googleapis.com/urlshortener/v1/url?pp=1";

    @RequestMapping(value = "/shorten", method = RequestMethod.GET)
    public String shortenUrl(Model model) {
        model.addAttribute("form", new ShortenUrlForm());

        return "url/url";
    }

    @RequestMapping(value = "/shorten", method = RequestMethod.POST)
    public String search(@ModelAttribute("form")
    @Valid
    ShortenUrlForm form, BindingResult results, Model model) {
        if (form == null) {
            return "main";
        }

        if (results.hasErrors()) {
            return "url/url";
        }

        try {
            List<String> scopes = Arrays.asList(new String[] { SHORTENER_URL });
            AppIdentityService appIdentity = AppIdentityServiceFactory
                    .getAppIdentityService();
            AppIdentityService.GetAccessTokenResult accessToken = appIdentity
                    .getAccessToken(scopes);
            JSONObject request = new JSONObject();
            request.put("longUrl", form.getUrl());

            URL url = new URL(SHORTENER_REQUEST_URL);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            connection.addRequestProperty("Content-Type", "application/json");
            connection.addRequestProperty("Authorization", "OAuth "
                    + accessToken.getAccessToken());

            OutputStreamWriter writer = new OutputStreamWriter(
                    connection.getOutputStream());
            request.write(writer);
            writer.close();

            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(connection.getInputStream(),
                                "UTF-8"));
                StringBuilder builder = new StringBuilder();
                for (String line = null; (line = reader.readLine()) != null;) {
                    builder.append(line).append("\n");
                }

                JSONTokener response_tokens = new JSONTokener(
                        builder.toString());
                JSONObject response = new JSONObject(response_tokens);

                form.setResult((String) response.get("id"));
                model.addAttribute("form", form);
            } else {
                throw new Exception();
            }
        } catch (JSONException e) {
            log.warning(String
                    .format("Problem with setting longUrl in JSONObject. URL: %s Exception: %s",
                            form.getUrl(), e.getMessage()));
        } catch (MalformedURLException e) {
            log.severe(String.format(
                    "Problem with creating URL object. Exception: %s",
                    e.getMessage()));
        } catch (IOException e) {
            log.severe(String.format(
                    "Problem with opening connection. Exception: %s",
                    e.getMessage()));
        } catch (Exception e) {
            log.info(String.format("Invalid response code. Exception: %s",
                    e.getMessage()));
        }

        return "url/url";
    }
}
